#ifndef PRIORITY_QUEUE_H
#define PRIORITY_QUEUE_H

#define ERR_PQUEUE_NULLARG           200
#define ERR_PQUEUE_MALFORMEDTREE     201
#define ERR_PQUEUE_EMPTYQUEUE        300
#define ERR_PQUEUE_FULLQUEUE         301
#define ERR_PQUEUE_ITEMNOTFOUND      400
#define ERR_PQUEUE_ITERATIONNOTREADY 500
#define ERR_PQUEUE_QUEUECHANGED      501

/****************************** Type Definitions ******************************/
struct priority_queue_node{
	struct priority_queue_node *left;
	struct priority_queue_node *parent;
	struct priority_queue_node *right;
	
	void *data;
};

typedef struct priority_queue_node pqn;
typedef struct priority_queue_node *ppqn;

struct priority_queue {
	int  (*compare_nodes)(void *, void *);
	int  (*delete_data)(void *);
	int  (*find)(void *, int, void **);
	
	int  queue_has_changed;
	
	long candidates_length;
	long length;
	
	ppqn root;
	ppqn *next_candidates;
};

typedef struct priority_queue pq;
typedef struct priority_queue *ppq;

/************************** ADT Function Prototypes ***************************/
int pq_init(
	ppq,
	int (*)(void *, void *),
	int (*)(void *),
	int (*)(void *, int, void **)
);
int pq_free(ppq);

int pq_find(ppq, int, void **, void **);
int pq_is_empty(ppq);
int pq_is_full(ppq);

int pq_dequeue(ppq, void **);
int pq_enqueue(ppq, void *);
int pq_remove(ppq, void *);
int pq_make_empty(ppq);

int pq_start_iteration(ppq);
int pq_get_next(ppq, void **);

#endif